#ifndef MCO_CLUSTER_H__
#define MCO_CLUSTER_H__

#ifdef __cplusplus
extern "C"
{
#endif 

#include <mco.h>
#include <mcotime.h>

#define MCO_MAX_CLUSTER_ADDRESS_LEN 64

#define MCO_MAX_CLUSTER_SIZE 32 /* max nodes num */

typedef void (*mco_cluster_transsize_f) (uint4 trans_size);
typedef mco_bool (*mco_cluster_check_quorum_f) (uint2 *neighbor_ids, uint2 n_neighbors, void *param);


typedef struct mco_cluster_node_params_t_ {
    char  addr[MCO_MAX_CLUSTER_ADDRESS_LEN];
    uint4 qrank;
} mco_cluster_node_params_t;


typedef struct mco_cluster_window_t_
{
    uint4                      bsize;  /* in bytes */
    uint4                      length; /* in transactions */
    timer_unit                 timeout;
} mco_cluster_window_t;

typedef struct mco_cluster_params_t_
{
    mco_cluster_node_params_t *nodes;
    uint2                      n_nodes;
    uint2                      node_id;
    uint2                      conn_pool_factor;
    uint4                      so_sndbuf;
    uint4                      so_rcvbuf;
    uint4                      sync_msg_objects; /* max number of objects per message during synchronization */
    uint4                      sync_msg_size;    /* max size of message in bytes during synchronization */
    timer_unit                 connect_timeout;
    timer_unit                 connect_interval;
    int                        socket_domain;
    mco_cluster_transsize_f    transsize_callback;
    timer_unit                 keepalive_time;
    uint4                      keepalive_probes;
    mco_cluster_check_quorum_f check_quorum_func;
    void                      *check_quorum_param;
    mco_cluster_window_t       window;
    
} mco_cluster_params_t, *mco_cluster_params_h;

typedef struct mco_cluster_info_t_
{
    uint4 rtrans_commit;
    uint4 rtrans_rback;
    uint8 bytes_sent;
    uint8 bytes_recv;
    uint2 n_active_nodes;
    uint2 node_id;
} mco_cluster_info_t, *mco_cluster_info_h;


MCO_RET mco_cluster_init();
MCO_RET mco_cluster_params_init(mco_cluster_params_t *cl_params);
MCO_RET mco_cluster_db_open(const char* db_name, mco_dictionary_h dict, mco_device_t * devs, 
                        mco_size_t n_devs, mco_db_params_t * db_params, mco_cluster_params_t * cl_params);
MCO_RET mco_cluster_listen(mco_db_h db);
MCO_RET mco_cluster_barrier(mco_db_h db);
MCO_RET mco_cluster_stop(mco_db_h db);
MCO_RET mco_cluster_detach(mco_db_h db);
MCO_RET mco_cluster_info(mco_db_h db, /* OUT */ mco_cluster_info_t *cl_info);

MCO_RET mco_cluster_get_window_params(mco_db_h db, mco_cluster_window_t * window_params);
MCO_RET mco_cluster_set_window_params(mco_db_h db, mco_cluster_window_t * window_params);

#ifdef __cplusplus
}
#endif 
#endif /* MCO_CLUSTER_H__         */
